package com.mustafaiev.tair.cts.dao.jpa;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;

import com.mustafaiev.tair.cts.dao.IBasketDAO;
import com.mustafaiev.tair.cts.exeption.DataNotRemovedException;
import com.mustafaiev.tair.cts.exeption.DataNotStoredException;
import com.mustafaiev.tair.cts.model.Basket;

/**
 * @author tair
 * 
 */
@Repository(value = "basketDao")
public class BasketDAO implements IBasketDAO {

	private static final String DELETE_FROM_BASKET_WHERE_ID = "delete from Basket where id = ?";

	private static final String SELECT_ALL_FROM_BASKET = "from Basket";

	private static final String SELECT_ALL_NON_BATCHED_FROM_BASKET = "from Basket where basketsBatchId is null";

	private static final String SELECT_ALL_BASKETS_FOR_BATCH = "from Basket where basketsBatchId = ?";

	private static final Logger LOGGER = Logger.getLogger(BasketDAO.class);

	private HibernateTemplate hibernateTemplate;

	@Autowired
	public void setHibernateTemplate(final HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	@Override
	public void doSave(final Basket t) throws DataNotStoredException {
		final Session session = this.hibernateTemplate.getSessionFactory()
				.openSession();
		final Transaction transaction = session.getTransaction();
		try {
			transaction.begin();
			session.saveOrUpdate(t);
			transaction.commit();
		} catch (final HibernateException e) {
			LOGGER.error(e);
			throw new DataNotStoredException(
					"Basket was not stored for a some reason", e);
		}
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Basket> retrieveBaskets() {
		final Session session = this.hibernateTemplate.getSessionFactory()
				.openSession();
		List<Basket> baskets = null;
		try {
			baskets = session.createQuery(SELECT_ALL_FROM_BASKET).list();
		} catch (final HibernateException e) {
			LOGGER.error(e);
		}
		return baskets;
	}

	@Override
	public Basket retrieveBasket(final Long basketId) {
		final Session session = this.hibernateTemplate.getSessionFactory()
				.openSession();
		Basket basket = null;
		try {
			basket = (Basket) session.get(Basket.class, basketId);
		} catch (final HibernateException e) {
			LOGGER.error(e);
		}
		return basket;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Basket> retrieveNonBatchedBaskets() {
		final Session session = this.hibernateTemplate.getSessionFactory()
				.openSession();
		List<Basket> baskets = null;
		try {
			baskets = session.createQuery(SELECT_ALL_NON_BATCHED_FROM_BASKET)
					.list();
		} catch (final HibernateException e) {
			LOGGER.error(e);
		}
		return baskets;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Basket> retrieveBasketsForBatch(final Long batchId) {
		final Session session = this.hibernateTemplate.getSessionFactory()
				.openSession();
		List<Basket> baskets = null;
		try {
			baskets = session.createQuery(SELECT_ALL_BASKETS_FOR_BATCH)
					.setLong(0, batchId).list();
		} catch (final HibernateException e) {
			LOGGER.error(e);
		}
		return baskets;
	}

	@Override
	public void deleteBatch(final List<Basket> baskets)
			throws DataNotRemovedException {
		final Session session = this.hibernateTemplate.getSessionFactory()
				.openSession();
		final Transaction transaction = session.getTransaction();
		try {
			transaction.begin();
			for (final Basket basket : baskets) {
				session.delete(basket);
			}
			transaction.commit();
		} catch (final HibernateException e) {
			LOGGER.error(e);
		}
	}

	@Override
	public void doDeleteById(final Long id) {
		final Session session = this.hibernateTemplate.getSessionFactory()
				.openSession();
		final Transaction transaction = session.getTransaction();
		try {
			transaction.begin();
			session.createQuery(DELETE_FROM_BASKET_WHERE_ID).setLong(0, id)
					.executeUpdate();
			transaction.commit();
		} catch (final HibernateException e) {
			LOGGER.error(e);
		}
	}

	@Override
	public void doDelete(final Basket t) throws DataNotRemovedException {

	}

	@Override
	public void doUpdate(final Basket t) throws DataNotStoredException {
		// TODO Auto-generated method stub

	}

}
